package org.linloong.utils;

import cn.hutool.core.io.IORuntimeException;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import lombok.extern.slf4j.Slf4j;
import org.linloong.config.audio.DifyAgentProperties;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.StringUtils;

import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 最新检测结果缓存管理
 *
 * @Author: kw
 * @date: 2025-11-13 19:35
 */
@Slf4j
public class CheckLastResultCacheUtil {
    private static final ThreadPoolTaskExecutor THREAD_POOL = new ThreadPoolTaskExecutor();

    private static final Cache<String, JSONObject> RESULT_CACHE = CacheBuilder.newBuilder()
            .expireAfterWrite(24, TimeUnit.HOURS)
            .build();

    private static final Cache<String, String> UPLOAD_FILEID_CACHE = CacheBuilder.newBuilder()
            .expireAfterWrite(24, TimeUnit.HOURS)
            .maximumSize(10000)
            .build();

    private static final JSONObject DEFAULT_RESULT = new JSONObject() {{
        put("detected", false);
        put("risk_level", 0);
    }};

    private static final Cache<String, String> REQUEST_CACHE = CacheBuilder.newBuilder()
            .expireAfterWrite(30, TimeUnit.SECONDS)
            .build();

    static {
        int threadCount = Runtime.getRuntime().availableProcessors();
        THREAD_POOL.setCorePoolSize(threadCount);
        THREAD_POOL.setMaxPoolSize(threadCount * 2);
        THREAD_POOL.setQueueCapacity(200);
        THREAD_POOL.setKeepAliveSeconds(60);
        THREAD_POOL.setThreadNamePrefix("result-thread-pool-");
        THREAD_POOL.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
        THREAD_POOL.initialize();
    }

    public static synchronized void addTask(String streamId, String url, DifyAgentProperties agentProperties, String auth) {
        boolean contain = REQUEST_CACHE.getIfPresent(streamId) != null;
        REQUEST_CACHE.put(streamId, url);
        if (contain) {
            log.info("任务已存在：{}", streamId);
            return;
        }
        log.info("添加新任务：{}", streamId);
        THREAD_POOL.execute(() -> {
            String useUrl;
            while ((useUrl = REQUEST_CACHE.getIfPresent(streamId)) != null) {
                long startTime = System.currentTimeMillis();
                try (HttpResponse response = HttpRequest.get(useUrl)
                        .timeout(500)
                        .execute()) {
                    long requestTime = System.currentTimeMillis() - startTime;
//                    log.info("{} 最新结果：{}", streamId, response.body());
                    JSONObject result = JSON.parseObject(response.body());
                    if (!result.containsKey("detected")) {
                        log.info("{} 最新结果错误：{}", streamId, response.body());
                        Thread.sleep(500);
                        continue;
                    }
                    String imageBase64 = result.getString("result_image_base64");
                    if (result.getBoolean("detected") && StringUtils.hasText(imageBase64)) {
                        long processStartTime = System.currentTimeMillis();
                        String key = MD5.create().digestHex16(imageBase64);
                        String uploadFileId = UPLOAD_FILEID_CACHE.getIfPresent(key);
                        if (uploadFileId == null) {
                            uploadFileId = DifyAgentUtil.uploadBase64File(
                                    imageBase64, agentProperties, auth, streamId
                            );
                            UPLOAD_FILEID_CACHE.put(key, uploadFileId);
                            long processTime = System.currentTimeMillis() - processStartTime;
                            log.info("文件上传耗时: {}ms", processTime);
                        }
                        result.put("uploadFileId", uploadFileId);
                    }
                    RESULT_CACHE.put(streamId, result);
                    long totalTime = System.currentTimeMillis() - startTime;
                    log.info("任务{}总耗时: {}ms, HTTP请求耗时: {}ms", streamId, totalTime, requestTime);
                    Thread.sleep(Math.max(500, 1000 - totalTime));
                } catch (IORuntimeException | HttpException e) {
                    long errorTime = System.currentTimeMillis() - startTime;
                    log.error("任务 {} 执行超时，耗时: {}ms，地址：{}", streamId, errorTime, useUrl);
                } catch (Exception e) {
                    long errorTime = System.currentTimeMillis() - startTime;
                    log.error("任务 {} 执行失败，耗时: {}ms", streamId, errorTime, e);
                }
            }
            log.info("任务 {} 已结束", streamId);
        });
    }

    public static JSONObject getResult(String streamId) {
        JSONObject result = RESULT_CACHE.getIfPresent(streamId);
        if (!CollectionUtils.isEmpty(result)) {
            return result;
        }
        return new JSONObject() {{
            put("detected", false);
            put("risk_level", 0);
            put("stream_id", streamId);
        }};
    }
}
